<?php

namespace app\health\controller;

use app\health\model\HealthUser;
use app\health\model\HealthUserAccount;
use app\health\model\HealthUserFriend;
use app\health\model\HealthUserStep;
use app\health\service\ConfigService;
use app\health\service\WeMiniService;
use think\Exception;
use think\Log;

/**
 * 用户健康+
 */
class UserHealth extends ApiBase
{
    /**
     * 获取健康+初始信息
     * @return void
     * @throws Exception
     */
    public function info(): void
    {
        $userStep  = HealthUserStep::where('user_id', $this->auth->id)
            ->where('day', date('Y-m-d'))->find();
        $clock_in  = $userStep['clock_in'] ?? 0;
        $day_step  = $userStep['step'] ?? 0;
        $goal_step = 10000;
        $this->backToData(compact('clock_in', 'day_step', 'goal_step'));
    }

    /**
     * 更新微信运动数据
     * @return void
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public function step_update(): void
    {
        $params = $this->request->param();
        if (!empty($params['code'])) {
            $weSession               = WeMiniService::getWeLoginSession($params['code']);
            $session_key             = $weSession['session_key'] ?? '';
            $this->auth->session_key = $session_key;
            HealthUser::where('id', $this->auth->id)->update(['session_key' => $session_key]);
        }
        $data = WeMiniService::decodeCrypt($params['iv'], $this->auth->session_key, $params['encryptedData']);
        Log::debug('[微信运动解密]:' . $this->auth->id . ':' . json_encode($data));
        if ($data !== false) {
            $stepInfoList = $data['stepInfoList'];
            $step         = $stepInfoList[count($stepInfoList) - 1]['step'];//步数
            $row          = HealthUserStep::where('user_id', $this->auth->id)
                ->where('day', date('Y-m-d'))->find();
            $goalStep     = ConfigService::getHealthPlusConfig()['goal_step'];
            if (!$row) {
                HealthUserStep::create([
                    'user_id'   => $this->auth->id,
                    'day'       => date('Y-m-d'),
                    'step'      => $step,
                    'goal_step' => $goalStep,
                ]);
            } else {
                $row->save(['step' => $step]);
            }
            $this->success('success', compact('step'));
        }
        $this->error('微信运动数据获取失败');
    }

    /**
     * 我的统计
     * @return void
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public function step_statistics(): void
    {
        $month      = $this->request->param('month', date('Y-m'));
        $start_date = date('Y-m-d', strtotime($month));
        $end_date   = date('Y-m-d', strtotime("$start_date +1 month -1 day"));
        $steps      = HealthUserStep::whereTime('day', 'between', [$start_date, $end_date])
            ->where('user_id', $this->auth->id)
            ->order('day', 'asc')
            ->field('day,step')
            ->select();
        //本月最高步数
        $max_step     = HealthUserStep::whereTime('day', 'month')->where('user_id', $this->auth->id)->max('step');
        $clock_in_day = HealthUserStep::whereTime('day', 'month')
            ->where('user_id', $this->auth->id)
            ->where('clock_in', 1)
            ->count();
        $this->backToData(compact('steps', 'month', 'max_step', 'clock_in_day'));
    }

    /**
     * 好友排行
     * @return void
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public function step_friend_ranking(): void
    {
        $friendId = $this->request->param('friend_uid/d', 0);
        $limit    = $this->request->param('limit/d', 30);
        $userIds  = [$this->auth->id];
        //查询我的好友
        $friend  = HealthUserFriend::where('user_id', $this->auth->id)->column('friend_user_id');
        $userIds = array_merge($userIds, $friend);
        if (is_array($friend) && $friendId > 0 && !in_array($friendId, $userIds, true) && HealthUser::where('id', $friendId)->count() > 0) {
            $userIds[] = $friendId;
            (new HealthUserFriend())->saveAll([
                ['user_id' => $this->auth->id, 'friend_user_id' => $friendId],
                ['user_id' => $friendId, 'friend_user_id' => $this->auth->id],
            ]);
        }
        $lists   = HealthUserStep::where('user_id', 'in', $userIds)
            ->with(['user'])
            ->whereTime('day', 'today')
            ->limit($limit)
            ->order('step', 'desc')
            ->select();
        $ranking = [];
        foreach ($lists as $list) {
            $ranking[] = [
                'day'      => $list->day,
                'step'     => $list->step,
                'nickname' => $list->user->nickname ?? '',
                'avatar'   => $list->user->avatar ?? '',
            ];
        }
        $this->backToData(compact('ranking'));
    }

    /**
     * 运动步数排行
     * @return void
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public function step_ranking(): void
    {
        $limit   = $this->request->param('limit/d', 30);
        $lists   = HealthUserStep::with(['user'])
            ->whereTime('day', 'today')
            ->limit($limit)
            ->order('step', 'desc')
            ->select();
        $ranking = [];
        foreach ($lists as $list) {
            $ranking[] = [
                'day'      => $list->day,
                'step'     => $list->step,
                'nickname' => $list->user->nickname ?? '',
                'avatar'   => $list->user->avatar ?? '',
            ];
        }
        $this->backToData(compact('ranking'));
    }

    /**
     * 健康+打卡
     * @return void
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public function clock_in(): void
    {
        $userStep = HealthUserStep::where('user_id', $this->auth->id)
            ->where('day', date('Y-m-d'))->find();
        if (!$userStep) {
            $this->error('请先同步微信运动步数');
        }
        if ($userStep['clock_in'] === 0) {
            $userStep->save(['clock_in' => 1, 'clock_in_at' => time()]);
            $this->success('打卡成功');
        }
        $this->error('今日已打卡');
    }

    /**
     * 奖励列表
     * @return void
     * @throws Exception
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public function award_lists(): void
    {
        $day_step  = HealthUserStep::whereTime('day', 'today')->where('user_id', $this->auth->id)->find();
        $todayGoal = 0;
        if ($day_step) {
            $todayGoal = $day_step['step'] >= $day_step['goal_step'] ? 1 : 0;
        }
        $clock_in   = $day_step['clock_in'] ?? 0;
        $get_status = 0;
        $list       = [
            [
                'title'  => '今日目标步数',
                'status' => $todayGoal,
            ],
            [
                'title'  => '今日打卡',
                'status' => $clock_in,
            ]
        ];
        if ($day_step) {
            if ($todayGoal === 1 && $clock_in === 1 && $day_step['is_get'] === 0) {
                $get_status = 1;
            } else if ($day_step['is_get'] === 1) {
                $get_status = 1;
            }
        }

        $this->backToData(compact('list', 'get_status'));
    }

    /**
     * 领取奖励
     * @return void
     * @throws Exception
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public function get_award(): void
    {
        $day_step = HealthUserStep::whereTime('day', 'today')->where('user_id', $this->auth->id)->find();
        $clock_in = $day_step['clock_in'] ?? 0;
        if ($day_step && $clock_in && $day_step['step'] >= $day_step['goal_step']) {
            if ($day_step['is_get'] === 1) {
                $this->error('奖励已领取');
            }
            $reward = [0.01, 0.02][random_int(0, 1)];
            HealthUserAccount::income(
                $this->auth->id,
                HealthUserAccount::FORM_TYPE_HEALTH_PLUS_EVERYDAY,
                HealthUserAccount::ACCOUNT_TYPE_BALANCE,
                $reward
            );
            HealthUser::where('id', $this->auth->id)->setInc('balance', $reward);
            $day_step->save(['is_get' => 1]);
            $this->success('领取成功', compact('reward'));
        }
        $this->error('未完成任务');
    }
}